package com.helwen.utils;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;

import com.helwen.config.JacksonConfig;
import com.helwen.constant.BaseEnum;
import com.helwen.tools.CommonPage;
import org.apache.http.client.utils.URIBuilder;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.net.URI;
import java.time.LocalDateTime;
import java.util.Arrays;

import static com.helwen.utils.DateFormatters.local_datetime_formatter;


/**
 * @author xay
 * @version 1.0
 * @since 2020/11/15
 */
public class RestTemplateUtil {

    public static final String IP = "127.0.0.1";
    public static final int PORT = 8105;
    public static final String AUTHORIZATION = "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJoZWx3ZW40NTYiLCJzY29wZSI6WyJhbGwiXSwidGVuYW50SWQiOiLplb_mspkiLCJhY2NpZCI6IjEzMjc1MDc5NTk4MDYzMDAxNjAiLCJpZCI6MTMyNzUwNzk1OTUxMjY5ODg4MCwidXNlclR5cGUiOiIxIiwiZXhwIjoxNjA2MTc5MzQ1LCJhdXRob3JpdGllcyI6WyI1X-i2hee6p-euoeeQhuWRmCJdLCJqdGkiOiIxY2NiZTViMS0xYWI4LTQwM2YtYmI2OC04NjZkN2YyZjU1YzkiLCJjbGllbnRfaWQiOiJzdG9yZS1hcHAiLCJ1c2VybmFtZSI6ImhlbHdlbjQ1NiIsInRva2VuIjoiMTlkN2U2ODBmZjliYzAwOTU4OGQ1MWNjNjQyZDZjMTAifQ.HFQ_dBwa7Jmveu6xY5JbHr0lNupLgmcwaP6OuRtM-c7Csr8faGaFbBHj1_2nHq5mqBqooBv1oOBvrVw6fZeoUcjV4f7dx3UzVx4DcMtGKLlo0MectE1Bo0m9FJYbZfrzBeGZA_w1qPfFsa4txZGIkIVsGbUDTE7vGAh66PeL_OQKJEXmNoRLg1wUdXOVtXMC2onGcN6VxiDpjfDO8-ZM2hBirjfojPkDBZSxfUBB3rC10bHvQWtBUwta1JFagEUNcPklBLsJrfjEcwCzz70k8sPPxShQBYAZiMKbHE-iUtFpX9nhL67d8gmMv71WU13FzETtAJ043vq4ie_6gcIc_g";
    public static final String AUTH_KEY="Authorization";

    public static RestTemplate getRestTemplate(){

        ObjectMapper objectMapper = new Jackson2ObjectMapperBuilder().createXmlMapper(false).build();
        // 全局配置序列化返回 JSON 处理
        SimpleModule simpleModule = new SimpleModule();
        //JSON Long ==> String
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(local_datetime_formatter));
        simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(local_datetime_formatter));
        simpleModule.addSerializer(BaseEnum.class, new JsonSerializer<BaseEnum>() {
            @Override
            public void serialize(BaseEnum value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                gen.writeObject(value.getValue());
            }
        });
        /*
         * TODO 类型条件限定过宽且仅做了名称处理
         * */
        simpleModule.addDeserializer(Enum.class, new JacksonConfig.CommonDeserializer());

        objectMapper.registerModule(simpleModule);
//        new RestTemplate()
        return new RestTemplate();
    }

    public static URIBuilder baseBuild(){
        return new URIBuilder().setScheme("http").setHost(IP).setPort(PORT);
    }
    public static URIBuilder builderPage(URIBuilder uriBuilder, CommonPage commonPage){
        if(null == commonPage)
            return uriBuilder;
        return uriBuilder.addParameter("pageNum", commonPage.getPageNum().toString())
                .addParameter("pageSize", commonPage.getPageSize().toString());
    }
    public static<T> ResponseEntity<T> get(URI uri, ParameterizedTypeReference clazz){
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        headers.add("Authorization",    AUTHORIZATION);
        HttpEntity<String> entity = new HttpEntity<>("parameters", headers);

        ResponseEntity<T> result = restTemplate.exchange(uri, HttpMethod.GET, entity, clazz);
        return result;
    }
    public static<T> ResponseEntity<T> get(String uri, ParameterizedTypeReference clazz){
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        headers.add("Authorization",    AUTHORIZATION);
        HttpEntity<String> entity = new HttpEntity<>("parameters", headers);

        ResponseEntity<T> result = restTemplate.exchange(uri, HttpMethod.GET, entity, clazz);
        return result;
    }

    public static <T> ResponseEntity<T> post(URI uri,Object body,ParameterizedTypeReference resultType){
        //拿到header信息
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.setContentType(MediaType.APPLICATION_JSON);
        requestHeaders.add(AUTH_KEY, AUTHORIZATION);

        HttpEntity requestEntity = null;
        try {
            requestEntity = new HttpEntity<>(toJson(body), requestHeaders);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return getRestTemplate().exchange(uri, HttpMethod.POST,requestEntity, resultType);
    }


    public static String toJson(Object o) throws JsonProcessingException {
        ObjectMapper objectMapper = new Jackson2ObjectMapperBuilder().createXmlMapper(false).build();
        // 全局配置序列化返回 JSON 处理
        SimpleModule simpleModule = new SimpleModule();
        //JSON Long ==> String
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(local_datetime_formatter));
        simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(local_datetime_formatter));
        simpleModule.addSerializer(BaseEnum.class, new JsonSerializer<BaseEnum>() {
            @Override
            public void serialize(BaseEnum value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                gen.writeObject(value.getValue());
            }
        });
        /*
         * TODO 类型条件限定过宽且仅做了名称处理
         * */
        simpleModule.addDeserializer(Enum.class, new JacksonConfig.CommonDeserializer());
        objectMapper.registerModule(simpleModule);
        return objectMapper.writeValueAsString(o);
    }
}
